package com.ctshk.common.utils;

import com.alibaba.nacos.common.codec.Base64;
import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ObjectUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 加签，加密，解密工具。
 * 我方加密私钥：MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCkC8DXIplbTY9f2ukvqny4y9kdOFV5/76GpnGX5VbjcVVrsiQRry8wA4LsoUV+YCgGx/83R19W/G0HA8dfDPbKu931x52IUgBcu/JZccJRZy5cmRC+VvY4ChL/etpiLJBG46nv1rkKlh723gzpStFgnKtVTatCkek3m38gfOo91x1+LnvrjSSlz9f6Oa5PUpPcXf7ZES/2bVCPWGB+uDMJ/nLRYQ1EEqIyFo9x4l77GYnyiuqPWrcuvr3YQ477aozpwuHJ74edch+CY8P9vOLpHCDoqA5yjTGerA6egq6FWZV+9urGjnMhWWUW3eu1LYKTuVfWxUgrB8XmPQclo7iZAgMBAAECggEAP0S5L0AM3YXgUhvf655ZU/xq1DYx4Uedd9kh3m95P2cqhsrB1oA2NtJj4FeiscbsKRFhgTRptObONfJjJmmdlTs3s981Bqp5sUpbgdu6EiM1Ykk2h/KKK7rW8Om06EA/tNeBZxrtawPTFWs2l5NfhV9nRRMbhiU4SVYThbgnr4lzbmgVqKe3EOkmDDNO3vmpnR+CVhr09HPJwO/QnqBal1tApWiqQmXd8jFsMkzOj/22YUXT18vCfnwzh0CN6/vc9s+Ua9IKv2tUWg/xbjphOmtsNB+6i5vxywOt5Ly4c4UmE+doTWcjvfjEIemIB8n1QAKF+lgvtNMC3kP8t2nGAQKBgQDyTMExCDHiEzcJdgrUHlYwagRn7CP6BISttQ0tLaHuzLoJH1FCvwqIyPX8YVchaC3gRpzHfaFanvHRm0d4ftqxi1pmU7XF+RZ1Mf90ydKQw1oJchQfTkE7E7Iygit7RbAimnTkDpg3cUxx0UglGqNF/FgI3zfZknRp3U4tZQ3JUQKBgQCtUkmkAjaZTdg4Pa1XrTup1GEhYbY0NXn5N/F9Tw0t63QOSsgL4E45LApZavVLTLWN4+BPk4fpr3RCsqxjK/bKSSyH/IAZ3S0osx5O+m3+KA+Q4mxoPbaozzmeHzsnQSUJd8G1znO64u3vzRVUqyFMVLLMynCbT9PmQF20KZwoyQKBgErPzhqgiB5ghm7CZqeF0mDSaxfXPmh0uq6Tp0TawRPlXE9yvvlX2R3QxrqtJ2TmMLv9sWya6pX7W3i3dALNUCLffwL3N7mvpfJ7hH9/zSbrWkJuWa4s0FE4TJ3xuREvvCmC/TJpGzCLJ+pAjwD9z4nNVzUuDqV75bvGG9xCRlZxAoGAWgCRHQnJMHKsBQiCKzVZ9ibDCYKkCxh57mCOlnOmdGIAMivDFee0txuXhDd2iVOcM8JRiQEjYsYpqTj/K8B4tzKoXTVRkBy6hpf89SY2V/SVoLbzdG4XnDF/ygyNuySpBvGZNb+veSy+QfhNS1pSQED7WD0HnJ8nejmSbyvsW4ECgYA6z3JnS/3czIHEFpkpYJVaxlQd4/IAMKl7p+ObMf5ecyH74wPk97pLUovnIJcBbmsFDApUobKsUJzg7uJ7vwHwaHWy+w8ErM/xocw+/GD2ODpmMCBEcK50MKFMoZEkM98uYqyFCcVjLj2faqDk9u+RL/C5eusjpuRElLTwg4NaVw==
 * 我方解密公钥：
 *
 * */
public class APISignUtil {
    //content --> 格式："{\"mer_no\":\"9000000242\",\"method\":\"chimelong.trip.park.info.get\",\"nonce_str\":\"80c5a87d22ed461bbe91ec691a4d9874\",\"timestamp\":\"2021-02-04 10:13:01\",\"ver_no\":\"1.0\",\"body\":\"{}\"}";
    public String contentJointTest(String content) {
        String signPrivateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCkC8DXIplbTY9f2ukvqny4y9kdOFV5/76GpnGX5VbjcVVrsiQRry8wA4LsoUV+YCgGx/83R19W/G0HA8dfDPbKu931x52IUgBcu/JZccJRZy5cmRC+VvY4ChL/etpiLJBG46nv1rkKlh723gzpStFgnKtVTatCkek3m38gfOo91x1+LnvrjSSlz9f6Oa5PUpPcXf7ZES/2bVCPWGB+uDMJ/nLRYQ1EEqIyFo9x4l77GYnyiuqPWrcuvr3YQ477aozpwuHJ74edch+CY8P9vOLpHCDoqA5yjTGerA6egq6FWZV+9urGjnMhWWUW3eu1LYKTuVfWxUgrB8XmPQclo7iZAgMBAAECggEAP0S5L0AM3YXgUhvf655ZU/xq1DYx4Uedd9kh3m95P2cqhsrB1oA2NtJj4FeiscbsKRFhgTRptObONfJjJmmdlTs3s981Bqp5sUpbgdu6EiM1Ykk2h/KKK7rW8Om06EA/tNeBZxrtawPTFWs2l5NfhV9nRRMbhiU4SVYThbgnr4lzbmgVqKe3EOkmDDNO3vmpnR+CVhr09HPJwO/QnqBal1tApWiqQmXd8jFsMkzOj/22YUXT18vCfnwzh0CN6/vc9s+Ua9IKv2tUWg/xbjphOmtsNB+6i5vxywOt5Ly4c4UmE+doTWcjvfjEIemIB8n1QAKF+lgvtNMC3kP8t2nGAQKBgQDyTMExCDHiEzcJdgrUHlYwagRn7CP6BISttQ0tLaHuzLoJH1FCvwqIyPX8YVchaC3gRpzHfaFanvHRm0d4ftqxi1pmU7XF+RZ1Mf90ydKQw1oJchQfTkE7E7Iygit7RbAimnTkDpg3cUxx0UglGqNF/FgI3zfZknRp3U4tZQ3JUQKBgQCtUkmkAjaZTdg4Pa1XrTup1GEhYbY0NXn5N/F9Tw0t63QOSsgL4E45LApZavVLTLWN4+BPk4fpr3RCsqxjK/bKSSyH/IAZ3S0osx5O+m3+KA+Q4mxoPbaozzmeHzsnQSUJd8G1znO64u3vzRVUqyFMVLLMynCbT9PmQF20KZwoyQKBgErPzhqgiB5ghm7CZqeF0mDSaxfXPmh0uq6Tp0TawRPlXE9yvvlX2R3QxrqtJ2TmMLv9sWya6pX7W3i3dALNUCLffwL3N7mvpfJ7hH9/zSbrWkJuWa4s0FE4TJ3xuREvvCmC/TJpGzCLJ+pAjwD9z4nNVzUuDqV75bvGG9xCRlZxAoGAWgCRHQnJMHKsBQiCKzVZ9ibDCYKkCxh57mCOlnOmdGIAMivDFee0txuXhDd2iVOcM8JRiQEjYsYpqTj/K8B4tzKoXTVRkBy6hpf89SY2V/SVoLbzdG4XnDF/ygyNuySpBvGZNb+veSy+QfhNS1pSQED7WD0HnJ8nejmSbyvsW4ECgYA6z3JnS/3czIHEFpkpYJVaxlQd4/IAMKl7p+ObMf5ecyH74wPk97pLUovnIJcBbmsFDApUobKsUJzg7uJ7vwHwaHWy+w8ErM/xocw+/GD2ODpmMCBEcK50MKFMoZEkM98uYqyFCcVjLj2faqDk9u+RL/C5eusjpuRElLTwg4NaVw==";
        // 1. 字符串拼接
        String contentJoint = contentJoint(content);
        System.out.println("contentJoint = " + contentJoint);
        // 2. 生成签名
        String sign = rsa256Sign(contentJoint, signPrivateKey);
        // 3. 加签，使用LinkedHashMap顺序添加
        Map<String, Object> contentWithNoSignMap = str2Map(content);
        Map<String, Object> contentWithSignMap = new LinkedHashMap<String, Object>();
        contentWithSignMap.put("method", contentWithNoSignMap.get("method"));
        contentWithSignMap.put("sign", sign);
        contentWithSignMap.put("nonce_str", contentWithNoSignMap.get("nonce_str"));
        contentWithSignMap.put("timestamp", contentWithNoSignMap.get("timestamp"));
        contentWithSignMap.put("ver_no", contentWithNoSignMap.get("ver_no"));
        contentWithSignMap.put("body", contentWithNoSignMap.get("body"));
        contentWithSignMap.put("mer_no",contentWithNoSignMap.get("mer_no"));
        System.out.println("contentWithSign = " + contentWithSignMap);
        // Map集合转JSON字符串
        String contentWithSignJson = json2Str(contentWithSignMap);
        System.out.println("contentWithSignJson = " + contentWithSignJson);
        return contentWithSignJson;
    }

    /**
     *签名内容JSON字符串拼接   暂时针对长隆接口使用
     */
    public static String contentJoint(String signContent) {

        Map<String, Object> signContentMap = str2Map(signContent);
        // 拼接请求参数
        String mer_no = ObjectUtils.toString(signContentMap.get("mer_no"));
        String method = ObjectUtils.toString(signContentMap.get("method"));
        String nonce_str = ObjectUtils.toString(signContentMap.get("nonce_str"));
        String timestamp = ObjectUtils.toString(signContentMap.get("timestamp"));
        String ver_no = ObjectUtils.toString(signContentMap.get("ver_no"));
        String body = ObjectUtils.toString(signContentMap.get("body"));

        StringBuilder builder = new StringBuilder();
        builder.append(mer_no);
        builder.append(method);
        builder.append(nonce_str);
        builder.append(timestamp);
        builder.append(ver_no);
        builder.append(body);

        return builder.toString();
    }

    /**
     * 将字符串转换成map对象
     */
    public static Map<String, Object> str2Map(String data) {
        ObjectMapper obj = new ObjectMapper();
        Map<String, Object> rtn = null;
        try {
            if(StringUtils.isNotBlank(data)) {
                rtn = obj.readValue(data, Map.class);
            }
        } catch(Exception e) {
            System.out.println("e = " + e);
        }
        if(rtn == null) {
            rtn = new HashMap<String, Object>();
        }
        return rtn;
    }

    /**
     * sha256WithRsa 加签
     */
    public static String rsa256Sign(String content, String privateKey) {
        try {
            String charset = "UTF-8";
            PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));

            if (priKey != null) {
                Signature signature = Signature.getInstance("SHA256WithRSA");
                signature.initSign(priKey);
                signature.update(content.getBytes(charset));

                byte[] signed = signature.sign();

                return new String(Base64.encodeBase64(signed));
            } else {
                return null;
            }
        } catch (Exception e) {
            System.out.println("e = " + e);
            return null;
        }
    }

    /**
     * 从PKCS8中转换成私有密钥
     */
    public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) {
        if (ins == null || StringUtils.isEmpty(algorithm)) {
            return null;
        }

        try {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            byte[] encodedKey = IOUtils.toByteArray(ins);
            encodedKey = Base64.decodeBase64(encodedKey);

            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
        } catch (Exception e) {
            System.out.println("e = " + e);
            return null;
        }
    }

    /**
     * 将对象转换成json字符串
     */
    public static String json2Str(Object data) {
        ObjectMapper obj = new ObjectMapper();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            JsonGenerator jg = obj.getJsonFactory().createJsonGenerator(baos, JsonEncoding.UTF8);
            jg.writeObject(data);
            return new String(baos.toByteArray(), "utf-8");
        } catch(IOException e) {
            return "";
        }
    }
}
